@* Generator: Template TypeVisibility: Internal *@
@using System.Globalization
@using System.IO
@using System.Web
@using Elmah
@inherits WebTemplateBase
@{
    var basePageName = Request.ServerVariables["URL"];

    // Read the error records.
    var log = this.ErrorLog ?? ErrorLog.GetDefault(Context);
    SearchCriteria sc = GetSearchCriteriaFromQueryString();
    var errorEntryList = new List<ErrorLogEntry>(sc.PageSize);
    int totalCount = log.GetErrors(sc, errorEntryList);

    //
    // Set the title of the page.
    //

    var hostName = Elmah.Environment.TryGetMachineName(Context);
    var title = string.Format(
        hostName.Length > 0
        ? "Error log for {0} on {2} (Page #{1})"
        : "Error log for {0} (Page #{1})",
        log.ApplicationName, (sc.PageIndex + 1).ToString("N0"), hostName);

    Layout = new Elmah.MasterPage
    {
        Context = Context, /* TODO Consider not requiring this */
        Title = title,
        Footnote = string.Format("This log is provided by the {0}.", log.Name),
        SpeedBarItems = new[] 
        {
            SpeedBar.RssFeed.Format(basePageName),
            SpeedBar.RssDigestFeed.Format(basePageName),
            SpeedBar.DownloadLog.Format(basePageName),
            SpeedBar.Help,
            SpeedBar.About.Format(basePageName),
        },
    };

    // If the application name matches the APPL_MD_PATH then its
    // of the form /LM/W3SVC/.../<name>. In this case, use only the 
    // <name> part to reduce the noise. The full application name is 
    // still made available through a tooltip.

    var simpleName = log.ApplicationName;

    if (string.Compare(simpleName, Request.ServerVariables["APPL_MD_PATH"],
        true, CultureInfo.InvariantCulture) == 0)
    {
        var lastSlashIndex = simpleName.LastIndexOf('/');

        if (lastSlashIndex > 0)
        {
            simpleName = simpleName.Substring(lastSlashIndex + 1);
        }
    }
}        

        <h1 id="PageTitle">
            Error Log for <span id="ApplicationName" title="@log.ApplicationName">@simpleName 
            @if (!string.IsNullOrEmpty(hostName))
            {
                <text> on @hostName</text> 
            }
            </span>
        </h1>
        
        @if (errorEntryList.Count > 0)
        {
            // Write error number range displayed on this page and the
            // total available in the log, followed by stock
            // page sizes.

            var firstErrorNumber = sc.PageIndex * sc.PageSize + 1;
            var lastErrorNumber = firstErrorNumber + errorEntryList.Count - 1;
            var totalPages = (int)Math.Ceiling((double)totalCount / sc.PageSize);

            // Write out a set of stock page size choices. Note that
            // selecting a stock page size re-starts the log 
            // display from the first page to get the right paging.

            var stockSizes =
                from sizes in new[]
                {
                    new[] { 10, 15, 20, 25, 30, 50, 100, },
                }
                from size in sizes.Index()
                let separator =
                    size.Key + 1 == sizes.Length
                    ? null
                    : size.Key + 2 == sizes.Length
                    ? " or "
                    : ", "
                select "<a href=\"\" onclick=\"javascript:DoSearch(0," + size.Value.ToString() + ");return false;\">" + size.Value.ToString("N0") + "</a>" + separator;
            
            <p>Errors @firstErrorNumber.ToString("N0") to @lastErrorNumber.ToString("N0") 
                of total @totalCount.ToString("N0") 
                (page @((sc.PageIndex + 1).ToString("N0")) of @totalPages.ToString("N0")). 
                Start with @Html(string.Join(null, stockSizes.ToArray())) errors per page.</p>

            // Write out the main table to display the errors.

            <table id="ErrorLog" cellspacing="0" style="border-collapse:collapse;" class="condensed-table zebra-striped">
                <tr>
                    <th class="host-col" style="white-space:nowrap;">Host</th>
                    <th class="code-col" style="white-space:nowrap;">Code</th>
                    <th class="type-col" style="white-space:nowrap;">Type</th>
                    <th class="error-col" style="white-space:nowrap;">Error</th>
                    <th class="user-col" style="white-space:nowrap;">User</th>
                    <th class="time-col" style="white-space:nowrap;">When</th>
                </tr>
				@if (log.SupportsSearching)
                {
					<tr>
						<td><input id="host" type="text" class="smallinput" onkeypress="HandleEnter(this, event);" value="@sc.Host"/></td>
						<td><input id="code" type="text" class="smallinput" onkeypress="HandleEnter(this, event);" value="@sc.StatusCode"/></td>
						<td><input id="type" type="text" class="smallinput" onkeypress="HandleEnter(this, event);" value="@sc.TypeName"/></td>
						<td><input id="error" type="text" class="largeinput" onkeypress="HandleEnter(this, event);" value="@sc.Message"/></td>
						<td><input id="user" type="text" class="smallinput" onkeypress="HandleEnter(this, event);" value="@sc.User"/></td>
						<td>
                            <input id="when" type="text" class="smallinput" onkeypress="HandleEnter(this, event);" value="@sc.When"/>
                            <br />
                            <a href="" onclick="javascript:DoSearch(); return false;">Search</a>
                        </td>
					</tr>
                }
                
            @foreach (var error in from item in errorEntryList.Index()
                                  let e = item.Value.Error
                                  select new
                                  {
                                      Index = item.Key,
                                      item.Value.Id,
                                      e.HostName,
                                      e.StatusCode,
                                      StatusDescription =
                                         e.StatusCode > 0
                                         ? HttpWorkerRequest.GetStatusDescription(e.StatusCode)
                                         : null,
                                      e.Type,
                                      HumaneType = ErrorDisplay.HumaneExceptionErrorType(e),
                                      e.Message,
                                      e.User,
                                      When = FuzzyTime.FormatInEnglish(e.Time),
                                      Iso8601Time = e.Time.ToString("o"),
                                  })
            {
                <tr class="@(error.Index % 2 == 0 ? "even" : "odd")">
                    
                    <td class="host-col" style="white-space:nowrap;">@error.HostName</td>
                    <td class="code-col" style="white-space:nowrap;">
                        @if (!string.IsNullOrEmpty(error.StatusDescription))
                        {
                            <span title="@error.StatusDescription">@error.StatusCode</span>
                        }
                        else if (error.StatusCode != 0)
                        {
                            @error.StatusCode
                        }
                    </td>
                    <td class="type-col" style="white-space:nowrap;"><span title="@error.Type">@error.HumaneType</span></td>
                    
                    <td class="error-col"><span>@error.Message</span> 
                        <a href="@basePageName/detail?id=@error.Id">Details&hellip;</a></td>
                    
                    <td class="user-col" style="white-space:nowrap;">@error.User</td>
                    <td class="time-col" style="white-space:nowrap;"><abbr title="@error.Iso8601Time">@error.When</abbr></td>
                </tr>
            }
            </table>

            // Write out page navigation links.

            //
            // If not on the last page then render a link to the next page.
            //

            var nextPageIndex = sc.PageIndex + 1;
            var moreErrors = nextPageIndex * sc.PageSize < totalCount;
            
            <p>

                @if (moreErrors)
                {
                    <a href="" onclick="javascript:DoSearch(@nextPageIndex,@sc.PageSize); return false;">Next errors</a>
                }
                @if (sc.PageIndex > 0 && totalCount > 0)
                {
                    if (moreErrors)
                    {
                        Write("; ");
                    }
                    <a href="" onclick="javascript:DoSearch(0,@sc.PageSize); return false;">Back to first page</a>
                }

            </p>
        }
        else
        {
            // No errors found in the log, so display a corresponding
            // message.

            // It is possible that there are no error at the requested 
            // page in the log (especially if it is not the first page).
            // However, if there are error in the log

            if (sc.PageIndex > 0 && totalCount > 0)
            {
                <p><a href="" onclick="javascript:DoSearch(0,@sc.PageSize); return false;">Go to first page</a>.</p>
            }
            else
            {
                <p>No errors found.</p>
                if (log.SupportsSearching)
                {
                <a href="" onclick="javascript:ClearSearch(); return false;">Clear Search</a>
                }
            }
        }

@functions
{
    SearchCriteria GetSearchCriteriaFromQueryString()
    {
        var sc = new SearchCriteria();

        int pageSize = Convert.ToInt32(Request.QueryString["pageSize"], CultureInfo.InvariantCulture);
        sc.PageSize = Math.Min(100, Math.Max(0, pageSize));
        if (sc.PageSize == 0)
            sc.PageSize = 15; 

        sc.PageIndex = Convert.ToInt32(Request.QueryString["pageIndex"], CultureInfo.InvariantCulture);
        if (sc.PageIndex < 0)
            sc.PageIndex = 0;

        sc.Host = Convert.ToString(Request.QueryString["host"], CultureInfo.InvariantCulture);
        sc.StatusCode = Convert.ToString(Request.QueryString["code"], CultureInfo.InvariantCulture);
        sc.TypeName = Convert.ToString(Request.QueryString["type"], CultureInfo.InvariantCulture);
        sc.Message = Convert.ToString(Request.QueryString["error"], CultureInfo.InvariantCulture);
        sc.User = Convert.ToString(Request.QueryString["user"], CultureInfo.InvariantCulture);
        sc.When = Convert.ToString(Request.QueryString["when"], CultureInfo.InvariantCulture);

        return sc;
    }
}

<script type="text/javascript">
function GetVal(txtBoxName) {
    var txtBox = document.getElementById(txtBoxName);
    var txtBoxVal = '';
    if (typeof txtBox !== 'undefined' && txtBox != null) {
        txtBoxVal = encodeURIComponent(txtBox.value);
    }
    return txtBoxVal;
}

function DoSearch(pageIndex, pageSize) {
    // Grab everything from the existing url, we need to get the
    // page index and size from here if they have been set previously.
    var args = location.search.substring(1).split('&');
    var params = {};
    for (var i = 0; i < args.length; i++) {
        var arg = args[i];
        if (arg.indexOf('=') > 0) {
            var kvp = arg.split('=');
            //params[kvp[0].trim()] = kvp[1].trim();
            params[kvp[0].replace(/^\s+|\s+$/g, "")] = kvp[1].replace(/^\s+|\s+$/g, "");
        }
    }

    // Overwrite with new page parameters, if specified.
    if (typeof pageIndex !== 'undefined') params['pageIndex'] = pageIndex + '';
    if (typeof pageSize !== 'undefined') params['pageSize'] = pageSize + '';

    // Overwrite with current contents of the search boxes.
    params['host'] = GetVal('host');
    params['code'] = GetVal('code');
    params['type'] = GetVal('type');
    params['error'] = GetVal('error');
    params['user'] = GetVal('user');
    params['when'] = GetVal('when');

    var s = '';
    for (var key in params) {
        var val = params[key];
        if (typeof val !== 'undefined' && val != '')
            s += '&' + key + '=' + val;
    }

    var url = location.protocol + '//' + location.hostname + location.pathname;
    if (s != '') url += '?' + s.substr(1);
    window.location = url;
}

function ClearSearch() {
    var url = location.protocol + '//' + location.hostname + location.pathname;
    window.location = url;
}

function HandleEnter(inField, e) {
    var charCode;

    if (e && e.which) {
        charCode = e.which;
    } else if (window.event) {
        e = window.event;
        charCode = e.keyCode;
    }

    if (charCode == 13) {
        DoSearch();
    }
}
</script>